#pragma once

#include <math.h>
#include <stdlib.h>
#include "mtypes.h"

#define _MAXNAMELENGTH_  100

// common.h
namespace com
{
#ifndef M_PI
#define M_PI   3.14159265358979323846f
#endif
#define _2PI   6.283185307179586f
#define PI M_PI
#define PI_2   1.570796326794897f
#define PI_180 0.0261799387799149f

     template <typename scalar>
       inline scalar sqr(const scalar& t) {return t * t;};

     template <typename scalar>
       inline scalar mod(scalar a, scalar b) 
       {
         scalar result = a % b;
         if (result >= 0)
         {
           return result;
         }
         else
         {
           return result + b;
         }
       }

     inline mFloat mod(mFloat a, mFloat b) 
     {
       return fmodf(a, b);
     }

     template <typename scalar>
	     inline scalar grad2rad(scalar angle) {return static_cast<scalar>(angle * PI_180);};

     template <typename scalar>
  	     inline scalar rad2grad(scalar angle) {return static_cast<scalar>(angle / PI_180);};

     inline mFloat frand(mFloat Min, mFloat Max, mFloat prec = 0.001f)
     {
       if (Min > Max)
         return 0.0f;
       if (Min == Max)
         return Min;
       return Min + prec * (mFloat)( rand() % long( (Max - Min) / prec) + 1 );
     }

     template <typename Real>
     mVoid clamp(Real* value, const Real min, const Real max) 
     {
         if( (*value) > max) 
         {
             (*value) = max;
         }
         else 
         {
             if( (*value) < min) 
             {
                 (*value) = min;
             }
         }
     }

     template <typename scalar>
     scalar maximum(const scalar a, const scalar b) 
     {
         return ( (a > b) ? (a) : (b) );
     }

     template <typename scalar>
     scalar minimum(const scalar a, const scalar b) 
     {
         return ( (a < b) ? (a) : (b) );
     }

     template <typename Real>
     Real Sign(const Real a) 
     {
         return ( (a < 0.0)? (-1.0): ( (a == 0.0)? (0.0):(1.0) ) );
     }

     template <typename Real>
     Real coTan(const Real vIn) {
         return (Real)-tan(vIn+PI_2);
     }

     template <typename Real>
     Real relativeEpsilon(const Real a, const Real epsilon) 
     {
         return maximum(fabs(a*epsilon),epsilon);
     }

     template <typename Real>
     mBool equal(const Real a, const Real b, const Real epsilon) 
     {
         return (fabs(a - b) < epsilon);
     }

     template <typename Real>
     mInt32 alike(const Real a, const Real b, const Real epsilon) {
         if(a == b) 
         {
             return 1;
         }
		 Real relEps = relativeEpsilon(a,epsilon);
		 return (a-relEps <= b) && (b <= a+relEps);
     }

     template <typename scalar>
     struct RECT
     {
       RECT() {}
       RECT(scalar x, scalar y, scalar width, scalar height): X(x), Y(y), Width(width), Height(height) {}
       scalar X, Y, Width, Height;
     };

}